home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / lib / calc / poly.cal < prev    next >
Text File  |  1995-07-17  |  18KB  |  729 lines

  1. /* 
  2.  * A collection of functions designed for calculations involving
  3.  *     polynomials in one variable (by Ernest W. Bowen).
  4.  *
  5.  * On starting the program the independent variable has identifier x
  6.  *    and name "x", i.e. the user can refer to it as x, the
  7.  *    computer displays it as "x".  The name of the independent
  8.  *    variable is stored as varname, so, for example, varname = "alpha"
  9.  *    will change its name to "alpha".  At any time, the independent
  10.  *    variable has only one name.  For some purposes, a name like
  11.  *    "sin(t)" or "(a + b)" or "\lambda" might be useful;
  12.  *    names like "*" or "-27" are legal but might give expressions
  13.  *    that are difficult to intepret.
  14.  *
  15.  * Polynomial expressions may be constructed from numbers and the
  16.  *    independent variable and other polynomials by the algebraic
  17.  *    operations +, -, *, ^, and if the result is a polynomial /.
  18.  *    The operations // and % are defined to have the quotient and
  19.  *    remainder meanings as usually defined for polynomials.
  20.  *
  21.  * When polynomials are assigned to idenfifiers, it is convenient to
  22.  *    think of the polynomials as values.  For example, p = (x - 1)^2
  23.  *    assigns to p a polynomial value in the same way as q = (7 - 1)^2
  24.  *    would assign to q a number value.  As with number expressions
  25.  *    involving operations, the expression used to define the
  26.  *    polynomial is usually lost; in the above example, the normal
  27.  *    computer display for p will be  x^2 - 2x + 1.  Different
  28.  *    identifiers may of course have the same polynomial value.
  29.  * 
  30.  * The polynomial we think of as a_0 + a_1 * x + ... + a_n * x^n,
  31.  *    for number coefficients a_0, a_1, ... a_n may also be
  32.  *    constructed as pol(a_0, a_1, ..., a_n).  Note that here the
  33.  *    coefficients are to be in ascending power order.  The independent
  34.  *    variable is pol(0,1), so to use t, say, as an identifier for
  35.  *    this, one may assign  t = pol(0,1).  To simultaneously specify
  36.  *    an identifier and a name for the independent variable, there is
  37.  *    the instruction var, used as in identifier = var(name).  For
  38.  *    example, to use "t" in the way "x" is initially, one may give
  39.  *    the instruction  t = var("t").
  40.  *
  41.  * There are four parameters pmode, order, iod and ims for controlling
  42.  *    the format in which polynomials are displayed.
  43.  *    The parameter pmode may have values "alg" or "list": the
  44.  *    former gives a display as an algebraic formula, while
  45.  *    the latter only lists the coefficients.  Whether the terms or
  46.  *    coefficients are in ascending or descending power order is
  47.  *    controlled by order being "up" or "down".  If the
  48.  *    parameter iod (for integer-only display), the polynomial
  49.  *    is expressed in terms of a polynomial whose coefficients are
  50.  *    integers with gcd = 1, the leading coefficient having positive
  51.  *    real part, with where necessary a leading multiplying integer,
  52.  *    a Gaussian integer multiplier if the coefficients are complex
  53.  *    with a common complex factor, and a trailing divisor integer.
  54.  *    If a non-zero value is assigned to the parameter ims,
  55.  *    multiplication signs will be inserted where appropriate;
  56.  *    this may be useful if the expression is to be copied to a
  57.  *    program or a string to be used with eval. 
  58.  *
  59.  * For evaluation of polynomials the standard function is ev(p, t).
  60.  *    If p is a polynomial and t anything for which the relevant
  61.  *    operations can be performed, this returns the value of p
  62.  *    at t.  The function ev(p, t) also accepts lists or matrices
  63.  *    as possible values for p; each element of p is then evaluated
  64.  *    at t.  For other p, t is ignored and the value of p is returned.
  65.  *    If an identifier, a, say, is used for the polynomial, list or
  66.  *    matrix p, the definition
  67.  *            define a(t) = ev(a, t);
  68.  *    permits a(t) to be used for the value of a at t as if the
  69.  *    polynomial, list or matrix were a function.  For example,
  70.  *    if a = 1 + x^2, a(2) will return the value 5, just as if
  71.  *            define a(t) = 1 + t^2;
  72.  *    had been used.   However, when the polynomial definition is
  73.  *    used, changing the polynomial a will change a(t) to the value
  74.  *    of the new polynomial at t.  For example,
  75.  *    after 
  76.  *        L = list(x, x^2, x^3, x^4);
  77.         define a(t) = ev(a, t);
  78.  *    the loop
  79.  *        for (i = 0; i < 4; i++)
  80.  *            print ev(L[[i]], 5);
  81.  *    may be replaced by
  82.  *        for (i = 0; i < 4; i++) {
  83.  *            a = L[[i]];
  84.  *            print a(5);
  85.  *        } 
  86.  *      
  87.  * Matrices with polynomial elements may be added, subtracted and
  88.  *    multiplied as long as the usual rules for compatibility are
  89.  *    observed.  Also, matrices may be multiplied by polynomials,
  90.  *    i.e. if p is a     polynomial and A a matrix whose elements
  91.  *    may be numbers or polynomials, p * A returns the matrix of
  92.  *    the same shape as A with each element multiplied by p.
  93.  *    Square matrices may also be 'substituted for the variable' in
  94.  *    polynomials, e.g. if A is an m x m matrix, and
  95.  *    p = x^2 + 3 * x + 2, ev(p, A) returns the same as
  96.  *    A^2 + 3 * A + 2 * I, where I is the unit m x m matrix.  
  97.  *    
  98.  * On starting this program, three demonstration polynomials a, b, c
  99.  *    have been defined.  The functions a(t), b(t), c(t) corresponding
  100.  *    to a, b, c, and x(t) corresponding to x, have also been
  101.  *    defined, so the usual function notation can be used for
  102.  *    evaluations of a, b, c and x.  For x, as long as x identifies
  103.  *    the independent variable, x(t) should return the value of t,
  104.  *    i.e. it acts as an identity function.
  105.  *    
  106.  * Functions defined include:
  107.  *
  108.  *    monic(a) returns the monic multiple of a, i.e., if a != 0,
  109.  *        the multiple of    a with leading coefficient 1    
  110.  *    conj(a) returns the complex conjugate of a
  111.  *    ispmult(a,b) returns 1 or 0 according as a is or is not
  112.  *        a polynomial multiple of b
  113.  *    pgcd(a,b) returns the monic gcd of a and b 
  114.  *    pfgcd(a,b) returns a list of three polynomials (g, u, v)
  115.  *        where g = pgcd(a,b) and g = u * a + v * b.
  116.  *    plcm(a,b) returns the monic lcm of a and b
  117.  *
  118.  *    interp(X,Y,t) returns the value at t of the polynomial given
  119.  *        by Newtonian divided difference interpolation, where
  120.  *        X is a list of x-values, Y a list of corresponding
  121.  *        y-values.  If t is omitted, the interpolating
  122.  *        polynomial is returned.  A y-value may be replaced by
  123.  *        list (y, y_1, y_2, ...), where y_1, y_2, ... are
  124.  *        the reduced derivatives at the corresponding x;
  125.  *        i.e. y_r is the r-th derivative divided by fact(r).
  126.  *    mdet(A) returns the determinant of the square matrix A,
  127.  *        computed by an algorithm that does not require
  128.  *        inverses;  the built-in det function usually fails
  129.  *        for matrices with polynomial elements.  
  130.  *    D(a,n) returns the n-th derivative of a; if n is omitted,
  131.  *        the first derivative is returned.
  132.  *
  133.  * A first-time user can see what the initially defined polynomials
  134.  *    a, b and c are, and experiment with the algebraic operations
  135.  *    and other functions that have been defined by giving
  136.  *    instructions like:
  137.  *            a
  138.  *            b
  139.  *            c
  140.  *            (x^2 + 1) * a
  141.  *            a^27
  142.  *            a * b    
  143.  *            a % b
  144.  *            a // b
  145.  *            a(1 + x)
  146.  *            a(b)
  147.  *            conj(c)
  148.  *            g = pgcd(a, b)
  149.  *            g
  150.  *            a / g
  151.  *            D(a)
  152.  *            mat A[2,2] = {1 + x, x^2, 3, 4*x}
  153.  *            mdet(A)
  154.  *            D(A)
  155.  *            A^2
  156.  *            define A(t) = ev(A, t)
  157.  *            A(2)
  158.  *            A(1 + x)
  159.  *            define L(t) = ev(L, t)
  160.  *            L = list(x, x^2, x^3, x^4)
  161.  *            L(5)
  162.  *            a(L)
  163.  *            interp(list(0,1,2,3), list(2,3,5,7))
  164.  *            interp(list(0,1,2), list(0,list(1,0),2))
  165.  *
  166.  * One check on some of the functions is provided by the Cayley-Hamilton
  167.  *    theorem:  if A is any m x m matrix and I the m x m unit matrix,
  168.  *    and x is pol(0,1),
  169.  *            ev(mdet(x * I - A), A)
  170.  *    should return the zero m x m matrix.
  171.  */
  172.  
  173. obj poly {p};
  174.  
  175. define pol() {
  176.     local u,i,s;
  177.     obj poly u;
  178.     s = list();
  179.     for (i=1; i<= param(0); i++) append (s,param(i));
  180.     i=size(s) -1;
  181.     while (i>=0 && s[[i]]==0) {i--; remove(s)}
  182.     u.p = s;
  183.     return u;
  184. }
  185.  
  186. define ispoly(a) {
  187.     local y;
  188.     obj poly y;
  189.     return istype(a,y);
  190. }
  191.  
  192. define findlist(a) {
  193.     if (ispoly(a)) return a.p;
  194.     if (a) return list(a);
  195.     return list();
  196. }
  197.  
  198. pmode = "alg";    /* The other acceptable pmode is "list" */
  199. ims = 0;    /* To be non-zero if multiplication signs to be inserted */
  200. iod = 0;    /* To be non-zero for integer-only display */
  201. order = "down"    /* Determines order in which coefficients displayed */
  202.  
  203. define poly_print(a) {
  204.     local f, g, t;
  205.     if (size(a.p) == 0) {
  206.         print 0:;
  207.         return;
  208.     } 
  209.     if (iod) {
  210.         g = gcdcoeffs(a);
  211.         t = a.p[[size(a.p) - 1]] / g;
  212.         if (re(t) < 0) { t = -t; g = -g;}
  213.         if (g != 1) {
  214.             if (!isreal(t)) {
  215.                 if (im(t) > re(t)) g *= 1i;
  216.                 else if (im(t) <= -re(t)) g *= -1i;
  217.             }
  218.             if (isreal(g)) f = g;
  219.             else f = gcd(re(g), im(g));
  220.             if (num(f) != 1) {
  221.                 print num(f):;
  222.                 if (ims) print"*":;
  223.             }
  224.             if (!isreal(g)) {
  225.                 printf("(%d)", g/f);
  226.                 if (ims) print"*":;
  227.             }
  228.             if (pmode == "alg") print"(":;
  229.             polyprint(1/g * a);
  230.             if (pmode == "alg") print")":;
  231.             if (den(f) > 1) print "/":den(f):;
  232.             return;
  233.         }
  234.     }
  235.     polyprint(a);
  236. }
  237.  
  238. define polyprint(a) {
  239.     local s,n,i,c;
  240.     s = a.p;
  241.     n=size(s) - 1;
  242.     if (pmode=="alg") {
  243.         if (order == "up") {
  244.             i = 0;
  245.             while (!s[[i]]) i++;
  246.             pterm (s[[i]], i);
  247.             for (i++ ; i <= n; i++) {
  248.                 c = s[[i]];
  249.                 if (c) {
  250.                     if (isreal(c)) {
  251.                         if (c > 0) print" + ":;
  252.                         else {
  253.                             print" - ":;
  254.                             c = -c;
  255.                         }
  256.                     } 
  257.                     else print " + ":;
  258.                     pterm(c,i);
  259.                 }
  260.             }
  261.             return;
  262.         }
  263.         if (order == "down") {
  264.             pterm(s[[n]],n);
  265.             for (i=n-1; i>=0; i--) {
  266.                 c = s[[i]];
  267.                 if (c) {
  268.                     if (isreal(c)) {
  269.                         if (c > 0) print" + ":;
  270.                         else {
  271.                             print" - ":;
  272.                             c = -c;
  273.                         }
  274.                     } 
  275.                     else print " + ":;
  276.                     pterm(c,i);
  277.                 }
  278.             }
  279.             return;
  280.         }
  281.         quit "order to be up or down";
  282.     }
  283.     if (pmode=="list") {
  284.         plist(s);
  285.         return;
  286.     }
  287.     print pmode,:"is unknown mode";
  288. }
  289.         
  290.  
  291. define poly_neg(a) {
  292.     local s,i,y;
  293.     obj poly y;
  294.     s = a.p;
  295.     for (i=0; i< size(s); i++) s[[i]] = -s[[i]];
  296.     y.p = s;
  297.     return y;
  298. }
  299.  
  300. define poly_conj(a) {
  301.     local s,i,y;
  302.     obj poly y;
  303.     s = a.p;
  304.     for (i=0; i < size(s); i++) s[[i]] = conj(s[[i]]);
  305.     y.p = s;
  306.     return y;
  307. }
  308.  
  309. define poly_inv(a) = pol(1)/a;    /* This exists only for a of zero degree */
  310.  
  311. define poly_add(a,b) {
  312.     local sa, sb, i, y;
  313.     obj poly y;
  314.     sa=findlist(a); sb=findlist(b);
  315.     if (size(sa) > size(sb)) swap(sa,sb);
  316.     for (i=0; i< size(sa); i++) sa[[i]] += sb[[i]];    
  317.     while (i < size(sb)) append (sa, sb[[i++]]);
  318.     while (i > 0 && sa[[--i]]==0) remove (sa);
  319.     y.p = sa;
  320.     return y;
  321. }
  322.  
  323. define poly_sub(a,b) {
  324.      return a + (-b);
  325. }
  326.  
  327. define poly_cmp(a,b) {
  328.     local sa, sb;
  329.     sa = findlist(a);
  330.     sb=findlist(b);
  331.     return  (sa != sb);
  332. }
  333.  
  334. define poly_mul(a,b) {
  335.     local sa,sb,i, j, y;
  336.     if (ismat(a)) swap(a,b);
  337.     if (ismat(b)) {
  338.         y = b;
  339.         for (i=matmin(b,1); i <= matmax(b,1); i++)
  340.             for (j = matmin(b,2); j<= matmax(b,2); j++)
  341.                 y[i,j] = a * b[i,j];
  342.         return y;    
  343.     }
  344.     obj poly y;
  345.     sa=findlist(a); sb=findlist(b);
  346.     y.p = listmul(sa,sb);
  347.     return y;
  348.  
  349. define listmul(a,b) {
  350.     local da,db, s, i, j, u;
  351.     da=size(a)-1; db=size(b)-1;
  352.     s=list();
  353.     if (da >= 0 && db >= 0) {
  354.         for (i=0; i<= da+db; i++) { u=0;
  355.             for (j = max(0,i-db); j <= min(i, da); j++)
  356.             u += a[[j]]*b[[i-j]]; append (s,u);}}
  357.     return s;
  358. }
  359.  
  360. define ev(a,t) {
  361.     local v, i, j;
  362.     if (ismat(a)) {
  363.         v = a;
  364.         for (i = matmin(a,1); i <= matmax(a,1); i++)
  365.             for (j = matmin(a,2); j <= matmax(a,2); j++)
  366.                 v[i,j] = ev(a[i,j], t);
  367.         return v;
  368.     }
  369.     if (islist(a)) {
  370.         v = list();
  371.         for (i = 0; i < size(a); i++)
  372.             append(v, ev(a[[i]], t));
  373.         return v;
  374.     }
  375.     if (!ispoly(a)) return a;
  376.     if (islist(t)) {
  377.         v = list();
  378.         for (i = 0; i < size(t); i++)
  379.             append(v, ev(a, t[[i]]));
  380.         return v;
  381.     }    
  382.     if (ismat(t)) return evpm(a.p, t);
  383.     return evp(a.p, t); 
  384. }
  385.  
  386. define evp(s,t) {
  387.     local n,v,i;
  388.     n = size(s);
  389.     if (!n) return 0;
  390.     v = s[[n-1]];
  391.     for (i = n - 2; i >= 0; i--) v=t * v +s[[i]];
  392.     return v;
  393. }
  394.  
  395. define evpm(s,t) {
  396.     local m, n, V, i, I;
  397.     n = size(s);
  398.     m = matmax(t,1) - matmin(t,1);
  399.     if (matmax(t,2) - matmin(t,2) != m) quit "Non-square matrix";
  400.     mat V[m+1, m+1];
  401.     if (!n) return V;
  402.     mat I[m+1, m+1];
  403.     matfill(I, 0, 1);
  404.     V = s[[n-1]] * I;
  405.     for (i = n - 2; i >= 0; i--) V = t * V + s[[i]] * I;
  406.     return V;
  407. }
  408. pzero = pol(0);
  409. x = pol(0,1); 
  410. varname = "x";
  411. define x(t) = ev(x, t);
  412.  
  413. define iszero(a) {
  414.     if (ispoly(a))
  415.         return !size(a.p);
  416.     return a == 0;
  417. }
  418.  
  419. define isstring(a) = istype(a, " ");
  420.  
  421. define var(name) {
  422.     if (!isstring(name)) quit "Argument of var is to be a string";
  423.     varname = name;
  424.     return pol(0,1);
  425. }
  426.  
  427. define pcoeff(a) {
  428.         if (isreal(a)) print a:;
  429.         else print "(":a:")":;
  430. }
  431.  
  432. define pterm(a,n) {
  433.     if (n==0) {
  434.         pcoeff(a);
  435.         return;
  436.     }
  437.     if (n==1) {
  438.         if (a!=1) {
  439.             pcoeff(a);
  440.             if (ims) print"*":;
  441.         }
  442.         print varname:;
  443.         return;
  444.     }
  445.     if (a!=1) {
  446.         pcoeff(a);
  447.         if (ims) print"*":;
  448.     }
  449.     print varname:"^":n:;
  450.  
  451. define plist(s) {
  452.     local i, n;
  453.     n = size(s);
  454.     print "( ":;
  455.     if (order == "up") {
  456.         for (i=0; i< n-1 ; i++)
  457.             print s[[i]]:",",:;
  458.         if (n) print s[[i]],")":;
  459.         else print "0 )":;
  460.     }
  461.     else {
  462.         if (n) print s[[n-1]]:;
  463.         for (i = n - 2; i >= 0; i--)
  464.             print ", ":s[[i]]:;
  465.         print " )":;
  466.     }
  467. }
  468.  
  469. define deg(a) = size(a.p) - 1;
  470.  
  471. define polydiv(a,b) {
  472.     local q, r, d, u, i, m, n, sa, sb, sq;
  473.     obj poly q, r;
  474.     sa=findlist(a); sb = findlist(b); sq = list();
  475.     m=size(sa)-1; n=size(sb)-1;
  476.     if (n<0) quit "Zero divisor";
  477.     if (m<n) return list(pzero, a);
  478.     d = sb[[n]]; 
  479.     while ( m >= n) { u = sa[[m]]/d;
  480.         for (i = 0; i< n; i++) sa[[m-n+i]] -= u*sb[[i]];
  481.         push(sq,u); remove(sa); m--;
  482.         while (m>=n && sa[[m]]==0) { m--; remove(sa); push(sq,0)}}
  483.     while (m>=0 && sa[[m]]==0) { m--; remove(sa);}
  484.     q.p = sq;  r.p = sa;
  485.     return list(q, r);}
  486.         
  487. define poly_mod(a,b)  {
  488.     local u;
  489.     u=polydiv(a,b);
  490.     return u[[1]];
  491. }
  492.  
  493. define poly_quo(a,b) {
  494.     local p;
  495.     p = polydiv(a,b);
  496.     return p[[0]];
  497. }
  498.  
  499. define ispmult(a,b) = iszero(a % b);
  500.  
  501. define poly_div(a,b) {
  502.     if (!ispmult(a,b)) quit "Result not a polynomial";
  503.     return poly_quo(a,b);
  504. }
  505.  
  506. define pgcd(a,b) {
  507.     local r;
  508.     if (iszero(a) && iszero(b)) return pzero;
  509.     while (!iszero(b)) {
  510.         r = a % b;
  511.         a = b;
  512.         b = r;
  513.     }
  514.     return monic(a);
  515. }
  516.  
  517. define plcm(a,b) = monic( a * b // pgcd(a,b));
  518.   
  519. define pfgcd(a,b) {
  520.     local u, v, u1, v1, s, q, r, d, w;
  521.     u = v1 = pol(1); v = u1 = pol(0);
  522.     while (size(b.p) > 0) {s = polydiv(a,b);
  523.         q = s[[0]];
  524.         a = b; b = s[[1]]; u -= q*u1; v -= -q*v1;
  525.         swap(u,u1); swap(v,v1);}
  526.     d=size(a.p)-1; if (d>=0 && (w= 1/a.p[[d]]) !=1)
  527.          { a *= w; u *= w; v *= w;}
  528.     return list(a,u,v);
  529. }
  530.   
  531. define monic(a) {
  532.     local s, c, i, d, y;
  533.     if (iszero(a)) return pzero;
  534.     obj poly y;
  535.     s = findlist(a);
  536.     d = size(s)-1;
  537.     for (i=0; i<=d; i++) s[[i]] /= s[[d]];
  538.     y.p = s;
  539.     return y;
  540. }
  541.  
  542. define coefficient(a,n) = (n < size(a.p)) ? a.p[[n]] : 0;
  543.  
  544. define D(a, n) {
  545.     local i,j,v;
  546.     if (isnull(n)) n = 1;
  547.     if (!isint(n) || n < 1) quit "Bad order for derivative";
  548.      if (ismat(a)) {
  549.         v = a;
  550.         for (i = matmin(a,1); i <= matmax(a,1); i++)
  551.             for (j = matmin(a,2); j <= matmax(a,2); j++)
  552.                 v[i,j] = D(a[i,j], n);
  553.         return v;
  554.     }
  555.     if (!ispoly(a)) return 0;
  556.     return Dp(a,n);
  557. }
  558.  
  559. define Dp(a,n) {
  560.     local i, v;
  561.     if (n > 1) return Dp(Dp(a, n-1), 1);
  562.      obj poly v;
  563.     v.p=list();    
  564.     for (i=1; i<size(a.p); i++) append (v.p, i*a.p[[i]]);
  565.     return v;
  566. }
  567.  
  568.  
  569. define cgcd(a,b) {
  570.     if (isreal(a) && isreal(b)) return gcd(a,b);
  571.     while (a) {
  572.         b -= bround(b/a) * a;
  573.         swap(a,b);
  574.     }
  575.     if (re(b) < 0) b = -b; 
  576.     if (im(b) > re(b)) b *= -1i;
  577.     else if (im(b) <= -re(b)) b *= 1i;
  578.     return b;
  579. }
  580.  
  581. define gcdcoeffs(a) {
  582.     local s,i,g, c;
  583.     s = a.p;
  584.     g=0;
  585.     for (i=0; i < size(s) && g != 1; i++)
  586.         if (c = s[[i]]) g = cgcd(g, c);
  587.     return g;
  588. }
  589.  
  590. define interp(X, Y, t) = evalfd(makediffs(X,Y), t);
  591.  
  592. define makediffs(X,Y) {
  593.     local U, D, d, x, y, i, j, k, m, n, s;
  594.     U = D = list();
  595.     n = size(X);
  596.     if (size(Y) != n) quit"Arguments to be lists of same size";
  597.     for (i = n-1; i >= 0; i--) {
  598.         x = X[[i]];
  599.         y = Y[[i]];
  600.         m = size(U);
  601.         if (isnum(y)) {
  602.             d = y;
  603.             for (j = 0; j < m; j++) {
  604.                 d = D[[j]] = (D[[j]]-d)/(U[[j]] - x);
  605.             }
  606.             push(U, x);
  607.             push(D, y);
  608.         }
  609.         else {
  610.             s = size(y);
  611.             for (k = 0; k < s ; k++) {
  612.                 d = y[[k]];
  613.                 for (j = 0; j < m; j++) {
  614.                     d = D[[j]] = (D[[j]] - d)/(U[[j]] - x);
  615.                 }
  616.             }
  617.             for (j=s-1; j >=0; j--) {
  618.                 push(U,x);
  619.                 push(D, y[[j]]);
  620.             }
  621.         }
  622.     }
  623.     return list(U, D);
  624. }
  625.     
  626. define evalfd(T, t) {
  627.     local U, D, n, i, v;
  628.     if (isnull(t)) t = pol(0,1);
  629.     U = T[[0]];
  630.     D = T[[1]];
  631.     n = size(U);
  632.     v = D[[n-1]];
  633.     for (i = n-2; i >= 0; i--) 
  634.         v = v * (t - U[[i]]) + D[[i]];
  635.     return v;
  636. }
  637.  
  638.  
  639. define mdet(A) {
  640.     local n, i, j, k, I, J;
  641.     n = matmax(A,1) - (i = matmin(A,1));
  642.     if (matmax(A,2) - (j = matmin(A,2)) != n)
  643.         quit "Non-square matrix for mdet";
  644.     I = J = list();
  645.     k = n + 1;
  646.     while (k--) {
  647.         append(I,i++);
  648.         append(J,j++);
  649.     }
  650.     return M(A, n+1, I, J);
  651. }
  652.  
  653. define M(A, n, I, J) {
  654.     local v, J0, i, j, j1;
  655.     if (n == 1) return A[ I[[0]], J[[0]] ];
  656.     v = 0;
  657.     i = remove(I);
  658.     for (j = 0; j < n; j++) {
  659.         J0 = J;
  660.         j1 = delete(J0, j);
  661.         v += (-1)^(n-1+j) * A[i, j1] * M(A, n-1, I, J0);
  662.     }
  663.     return v;
  664. }
  665.  
  666. define mprint(A) {
  667.     local i,j;
  668.     if (!ismat(A)) quit "Argument to be a matrix";
  669.     for (i = matmin(A,1); i <= matmax(A,1); i++) {
  670.         for (j = matmin(A,2); j <= matmax(A,2); j++)
  671.             printf("%8.4d ", A[i,j]);
  672.         printf("\n");
  673.     }
  674. }
  675.     
  676. obj poly a;
  677. obj poly b;
  678. obj poly c;
  679.  
  680. define a(t) = ev(a,t);
  681. define b(t) = ev(b,t);
  682. define c(t) = ev(c,t);
  683.  
  684. a=pol(1,4,4,2,3,1);
  685. b=pol(5,16,8,1);
  686. c=pol(1+2i,3+4i,5+6i);
  687.  
  688. global lib_debug;
  689. if (lib_debug >= 0) {
  690.     print "obj poly {p} defined";
  691.     print "pol() defined";
  692.     print "poly_print(a) defined";
  693.     print "poly_add(a, b) defined";
  694.     print "poly_sub(a, b) defined";
  695.     print "poly_mul(a, b) defined";
  696.     print "poly_div(a, b) defined";
  697.     print "poly_quo(a,b) defined";
  698.     print "poly_mod(a,b) defined";
  699.     print "poly_neg(a) defined";
  700.     print "poly_conj(a) defined";
  701.     print "poly_cmp(a,b) defined";
  702.     print "iszero(a) defined";
  703.     print "plist(a) defined";
  704.     print "listmul(a,b) defined";
  705.     print "ev(a,t) defined";
  706.     print "evp(s,t) defined";
  707.     print "ispoly(a) defined";
  708.     print "isstring(a) defined";
  709.     print "var(name) defined";
  710.     print "pcoeff(a) defined";
  711.     print "pterm(a,n) defined";
  712.     print "deg(a) defined";
  713.     print "polydiv(a,b) defined";
  714.     print "D(a,n) defined";
  715.     print "Dp(a,n) defined";
  716.     print "pgcd(a,b) defined";
  717.     print "plcm(a,b) defined";
  718.     print "monic(a) defined";
  719.     print "pfgcd(a,b) defined";
  720.     print "interp(X,Y,x) defined";
  721.     print "makediffs(X,Y) defined";
  722.     print "evalfd(T,x) defined";
  723.     print "mdet(A) defined";
  724.     print "M(A,n,I,J) defined";
  725.     print "mprint(A) defined";
  726. }
  727.